package utilities;

import NeuronNetworkLibrary.Network;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Utilities {

    /**
     * Converts Double ArrayList type into String ArrayList type.
     *
     * @param data Double ArrayList
     * @return String ArrayList
     */
    public static ArrayList<String> convertToStringArrayList(ArrayList<Double> data) {
        ArrayList<String> strings = new ArrayList<>();
        for (int i = 0; i < data.size(); i++) {
            strings.add(String.valueOf(data.get(i).doubleValue()));
        }
        return strings;
    }

    /**
     * Generate the training set from given inverval with given step.
     * @param min
     * @param max
     * @param step
     * @return training set
     */
    public static double[][] generateTrainingSet(double min, double max, double step) {

        ArrayList<Double> dataContainer = new ArrayList<>();
        for (double i = min; i <= max; i += step) {
            dataContainer.add(i);
        }

        double newSet[][] = new double[dataContainer.size()][1];
        for (int i = 0; i < dataContainer.size(); i++) {
                newSet[i][0] = dataContainer.get(i).doubleValue();
        }

        return newSet;
    }
    
    /**
     * Clean the string with unnecessary signs.
     * @param s String
     * @return String without unnecessary signs.
     */
    public static String cleanString(String s){
            s = s.replace("]", "");
            s = s.replace("[", "");
            s = s.replace(",", " ");
        return s;
    }
    
    /**
     * Reads and returns the last assigned weights in network
     * @param network 
     * @return 
     */
    public static ArrayList<String> readWeights(Network network) {

        ArrayList<String> weights = new ArrayList<>();
        for (int i = 0; i < network.getHiddenLayers().size(); i++) {
            for (int j = 0; j < network.getHiddenLayers().get(i).size(); j++) {

                double w[] = network.getHiddenLayers().get(i).get(j).getInputWeights();              
                weights.add(Arrays.toString(w));
            }
        }

        for (int i = 0; i < network.getOutputLayer().size(); i++) {

            double[] w1 = network.getOutputLayer().get(i).getInputWeights();
            weights.add(Arrays.toString(w1));
        }
        
        for (int i = 0; i < weights.size(); i++) {
            weights.set(i, cleanString(weights.get(i)));          
        }
        
        return weights;
    }
    
    /**
     * Generate training set from given INTERVALS (not single interval, but more!).
     * @param min
     * @param max
     * @param step
     * @return New training set.
     */
    public static double[][] generateTrainingSet(double[] min, double[] max, double step) {
        
        /**
         * TODO: make more re-usable!
         */
        int i=0;
//        ArrayList<ArrayList<Double>> all = new ArrayList<>();
//        for (int i = 0; i < max.length; i++) {
            
            ArrayList<Double> list = new ArrayList<>();
            for (double j = min[i]; j <= max[i]; j+=step) {
                list.add(j);               
            }
//            all.add(list);
//        }
        
        Double[] x = list.toArray(new Double[list.size()]);
        double[] x1 = new double[x.length];
        for (int j = 0; j < x.length; j++) {
            x1[j]=x[j].doubleValue(); 
        }
        
        Combinations com = new Combinations(x1, 3);
        List<double[]> v = com.getVariations();
//        for (double[] s : v) {
//            System.out.println(Arrays.toString(s));
//        }
//        System.out.println("Combinations: " + v.size());
        
        // Rewrite into a double[][] array.
        double[][] newTrainingSet = new double[v.size()][min.length];
        for (int j = 0; j < newTrainingSet.length; j++) {
            for (int k = 0; k < newTrainingSet[j].length; k++) {
                newTrainingSet[j][k] = v.get(j)[k];
            }
            
        }

        return newTrainingSet;
    } 
    
}
